from django.core.files.uploadedfile import InMemoryUploadedFile


from django.http import QueryDict, HttpResponse, JsonResponse
from django.shortcuts import render
from mongoengine import QuerySet, Q
from rest_framework import permissions, status
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.utils import json

from rest_framework_mongoengine import viewsets
import re

from authorshow.models.models import Author, Paper, StandardResultSetPagination, Venue
from authorshow.models.serializer import AuthorSerializer, PaperSerializer, ListAuthorSerializer, VenueSerializer
from authorshow.models.update import update_author_icon
from authorshow.models.utils import select_author, create_coll_id, select_research, select_research_org, \
    select_research_author


# url: /v1/authors
from expertwords.models import ExpertWords
from fullsearch.models import FullSearch


class AuthorViewSet(viewsets.ModelViewSet):
    """
    继承 ModelViewSet，需要给 serializer_class、queryset 两个属性赋值
    其中，serializer_class 是序列化类
    queryset 是查询集合
    """
    # 默认使用序列化类：AuthorSerializer，序列化全部字段
    serializer_class = AuthorSerializer
    queryset: QuerySet = Author.objects.all()
    # pagination_class 属性：默认分页类
    pagination_class = StandardResultSetPagination
    # 权限控制：管理员才能 post 操作创建新的数据
    permission_classes = (
        permissions.IsAuthenticatedOrReadOnly,
    )

    def perform_create(self, serializer):
        serializer.save()

    def perform_update(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

    def validate_request_data_and_pop(self, request_data: dict):
        if request_data.get('pubs') is not None:
            request_data.pop('pubs')
        if request_data.get('icon') is not None:
            request_data.pop('icon')
        if request_data.get('n_pubs') is not None:
            request_data.pop('n_pubs')

    def create(self, request, *args, **kwargs):
        """
        创建一个 author instance，request 中必须包含 name 属性，不需发送: id,pubs,icon，n_pubs
        pubs、icon。n_pubs 属性不会被新增
        """
        data = request.data

        data['id'] = str(create_coll_id(queryset=self.get_queryset()))
        self.validate_request_data_and_pop(data)
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(data=serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    # URL：/v1/authors/
    def list(self, request, *args, **kwargs):
        """
        列表所有的 author，
        :param request: 查询参数，可包含 name,h_index,pubs,org,keywords,n_pubs,n_citation,position
        :param args:
        :param kwargs:
        :return: 分页的数组数据
        """
        # 参数获取
        params = request.query_params
        name = params.get(key='name')
        # h_index = params.get(key='h_index')
        # pubs = params.get(key='pubs')
        org = params.get(key='org')
        keywords = params.get(key='keywords')
        # n_pubs = params.get(key='n_pubs')
        # n_citation = params.get(key='n_citation')
        # position = params.get(key='position')
        # 如果没有查询参数，列表全部数据
        if not (name or org or keywords):
            queryset = self.filter_queryset(self.get_queryset())
            page = self.paginate_queryset(queryset=queryset)
            serializer = ListAuthorSerializer(instance=page, many=True)
            return self.get_paginated_response(serializer.data)
        # 有查询参数
        r_result = select_author(queryset=self.queryset, name=name, org=org, keywords=keywords)
        # 未查询到结果
        if r_result is None or r_result.count() is 0:
        # if r_result is None or len(r_result) is 0:
            err_msg = "未查询到结果"
            return Response(data=err_msg, status=status.HTTP_404_NOT_FOUND)
        page = self.paginate_queryset(queryset=r_result)
        # 序列化所有字段
        serializer = ListAuthorSerializer(instance=page, many=True)
        return self.get_paginated_response(serializer.data)

    # url: .../update/
    def update(self, request, id=None, *args, **kwargs):
        """
        更新一个 author，request 中必须包含 name 属性，其他属性未包含则不会被修改，n_pubs，pubs、icon 属性不会被修改
        """
        instance: Author = self.get_object()
        data = request.data
        data['id'] = instance.id
        # 去掉 pubs、icon、n_pubs 字段
        self.validate_request_data_and_pop(data)
        serializer: AuthorSerializer = self.get_serializer(instance, data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        return Response(data=serializer.data)

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

    def destroy(self, request, *args, **kwargs):
        """
        删除一个作者信息,使用destroy方法不删除该作者对应的paper信息,因为同一文章可能有多个作者.
        注意：在下面定义的paper函数中的post方法,给不同作者添加同一文章时,自产生文章id号(create_coll_id)不同,
        即同一文章有不同的id,此时作者和文章是一一对应关系.此时,删除该作者信息和其对应的paper信息分别在v1/author和v1/paper中删除.
        """
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()
        # TODO 删除头像文件，删除 paper 里 author 外键

    # TODO 设置额外视图
    # 对应 url： /v1/authors/<id>/paper/
    # 具体url：http://localhost:8000/v1/authors/XXXX/papers/
    @action(detail=True, methods=['get', 'post'])
    def papers(self, request, id=None):
        """
        获取指定 author 的文章数据，返回数组值
        注意到post方法自生成文章id,且数据库中的作者和文章关系已经明确。
        因此对于同一作者的papers进行更新和删除操作均使用paper中update和destroy方法即可. -- 用于后期添加删除数据.
        """
        author = self.get_object()
        if request.method == 'GET':
            if author is None or author.pubs is None:
                err_msg = "抱歉，查询无结果"
                return Response(data=err_msg, status=status.HTTP_404_NOT_FOUND)
            else:
                papers = []
                n_pubs_range = range(len(author.pubs))
                for i in n_pubs_range:
                    papers.append(author.pubs[i].i.fetch())
                page = self.paginate_queryset(queryset=papers)
                serializer = PaperSerializer(instance=page, many=True)
                return self.get_paginated_response(data=serializer.data)
        # 添加 authors
        elif request.method == 'POST':
            data = request.data
            data['id'] = create_coll_id(Paper.objects)
            serializer: PaperSerializer = PaperSerializer(data=data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            # 为该 author 添加 paper
            author.pubs.create(i=data['id'], r=0)
            if author.n_pubs is None:
                author.n_pubs = 1
            else:
                author.n_pubs += 1
            author.save()
            return Response(data=serializer.data)


def keywords_rank(request):
    '''针对某一作者对应paper的关键词统计--生成关键词热点图'''
    '''url：http://localhost:8000/author_keywords_rank/?id=XXX
       获取排名前30的关键词进行展示。
    '''
    id = request.GET.get('id', None)      # 获取作者id
    if id == None:
        return HttpResponse('请提供作者 id 参数。')
    author = Author.objects.filter(id=id)[0]
    papers = []
    n_pubs_range = range(len(author.pubs))
    for i in n_pubs_range:
        papers.append(author.pubs[i].i.fetch())     # fetch 方法获取该作者对应的所有paper
    keywords = []
    author_keywords = {}

    # 问题：关键词的相似性的的统一(如Uniformity、consistence均是指一致性,但是基于数据无法判别)，这里不考虑这种情况,直接对paper关键词进行统计。
    for i in papers:
        if i.keywords is None:
            continue
        else:
            for j in range(len(i.keywords)):
                keywords.append(i.keywords[j])
    for i in keywords:
        if i in author_keywords:
            author_keywords[i] += 1
        else:
            author_keywords[i] = 1
    k = {}
    sort_rank = sorted(author_keywords.items(), key=lambda x: x[1], reverse=True)[:30]   # 获取排名前30的关键词
    for i in sort_rank:  # 将排序前10的关键词写入新的字典中
        k[i[0]] = author_keywords[i[0]]
    # return JsonResponse(k, json_dumps_params={'ensure_ascii': False})
    res = json.dumps(k, indent=4, ensure_ascii=False)
    return HttpResponse(res, content_type='application/json', charset='utf-8')

def author_tags_year(request):
    '''针对某一作者的年度研究领域按年发文量(研究领域对应paper的keywords)
       某作者对应的keywords较多，这里选取前n个最多的关键词进行展示。
       同research_year_author.
    '''
    id = request.GET.get('id', None)      # 获取作者id
    if id == None:
        return HttpResponse('请提供作者 id 参数。')
    author = Author.objects.filter(id=id)[0]
    papers = []
    a = {}
    b = {}
    n_pubs_range = range(len(author.pubs))
    for i in n_pubs_range:
        papers.append(author.pubs[i].i.fetch())
    for i in papers:
        if i.year is None:
            continue
        else:
            if i.keywords is None:
                continue
            else:
                # print(i.keywords)
                for j in i.keywords:
                    """由于某个作者可能在某年发表多篇文章,不能直接使用字典写入,因为字典键一般是唯一的"""
                    if j in a:
                        a[j].append(i.year)
                    else:
                        a[j] = [i.year]

    result_rank = {}
    k = {}
    for key, value in a.items():
        result_rank[key] = len(value)
    sort_rank = sorted(result_rank.items(), key=lambda x: x[1], reverse=True)[:5]  # 选取前5的关键词
    for i in sort_rank:  # 将排序前10的关键词写入新的字典中
        k[i[0]] = a[i[0]]

    for key, value in k.items():
        b[key] = {}
        for i in k[key]:
            if i in b[key]:
                b[key][i] += 1
            else:
                b[key][i] = 1
    # return JsonResponse(b, json_dumps_params={'ensure_ascii': False})
    res = json.dumps(b, indent=4, ensure_ascii=False)
    return HttpResponse(res, content_type='application/json', charset='utf-8')


class PaperViewSet(viewsets.ModelViewSet):
    """
    paper 数据集 api
    文档：https://www.django-rest-framework.org/api-guide/viewsets/
    """
    # -------------每个 ViewSet 类必备属性，分别是：序列化类（不同的类序列化集不同）、查询集合（不同类查询集不同）、分页类（不变）
    serializer_class = PaperSerializer
    queryset = Paper.objects
    pagination_class = StandardResultSetPagination
    # ---------------------------------------------------------------------------------

    # 权限控制：管理员才能创建、修改、删除数据
    permission_classes = (
        permissions.IsAuthenticatedOrReadOnly,
    )

    # --------- 创建操作（perform_create）、（更新perform_update、删除perform_destroy）------
    # 这些方法实际上在 create() 等方法中被调用
    def perform_create(self, serializer):
        serializer.save()

    def perform_update(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}
    # ------------------------------------------

    # TODO 实现 list、create、update、retrieve 等方法
    def list(self, request, *args, **kwargs):
        """
        功能：
        一、paper 数据全部展示，最后结果是分页展示的，对应 url：http://127.0.0.1:8000/v1/papers/
        二、查询，例：访问 http://127.0.0.1:8000/v1/papers/?title=1234，
            返回的结果集合是 title 包含 1234 的数据集
        api 文档：http://127.0.0.1:8000/docs/#papers-list
        """
        # 1. 参数获取，比如 http://127.0.0.1:8000/v1/papers/?title=1234，可使用 params.get('title') 方法获取 1234，如果没有则为 None
        params = request.query_params
        title = params.get('title')
        # 2. 判断 title 是否为空，如果为空，则展示所有数据，比如访问 http://127.0.0.1:8000/v1/papers/
        if title is None:
            queryset = self.get_queryset()  # 获取属性 queryset = Paper.objects
            # 分页和序列化，注意，序列化参数需要有 many=True，因为 page 结果是数组，包含多条数据，即便包含一条，也是一个数组
            page = self.paginate_queryset(queryset=queryset)
            serializer = self.get_serializer(instance=page, many=True)
            return self.get_paginated_response(serializer.data)
        else:
            # title 不为空，根据获取的 title 值，查询，r_result 为一个数据集，比如访问 http://127.0.0.1:8000/v1/papers/?title=1234
            r_result = self.get_queryset().filter(title__icontains=title)
            # 3. 未查询到结果
            if r_result.count() is 0:
                return Response(data="未查询到 paper 数据", status=status.HTTP_404_NOT_FOUND)
            # 4. 返回查询结果
            page = self.paginate_queryset(queryset=r_result)
            serializer = self.get_serializer(instance=page, many=True)
            return self.get_paginated_response(serializer.data)

    """
    retrieve：查询，对应文档是 http://127.0.0.1:8000/docs/#papers-read
        对应 url：/v1/papers/{id}/，其中 {id} 为 paper id，
        框架生成的 retrieve 方法满足要求，不需自己实现 retrieve
        比如访问：http://127.0.0.1:8000/v1/papers/53a7258520f7420be8b514a9/，获取指定 id 的数据
    create：创建，可参考 AuthorViewSet ，对应 post /v1/papers/
    update：修改
    destroy：删除
    """
    # def retrieve(self, request, *args, **kwargs):
    def create(self, request, *args, **kwargs):
        """
        创建一个 paper instance
        """
        request.data['id'] = str(create_coll_id(queryset=self.get_queryset()))
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(data=serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def update(self, request, id=None, *args, **kwargs):
        """
        更新一个 paper，未包含的属性不会被修改
        """
        instance: Paper = self.get_object()
        data: dict = request.data
        data['id'] = instance.id
        serializer: PaperSerializer = self.get_serializer(instance, data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        return Response(data=serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        删除一个paper instance, 同时删除对应作者的pubs信息且n_pubs自减1.
        """
        instance = self.get_object()
        # 需删除该paper对应的作者pubs信息,否则http://localhost:8000/v1/authors/XXXX/papers/ 出现错误。
        # 注意这里首先删除作者对应的pubs信息再删除paper信息,否则无法提取paper的id。
        id = instance.id
        for author in Author.objects.all():
            if author.pubs is not None:
                for paper in author.pubs:
                    if paper.i.fetch().id == id:
                        author.pubs.filter(i=paper.i).delete()
                        author.n_pubs -= 1
                        author.save()
                    else:
                        continue
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)


def research_year(request):
    '''科研热点库--由搜索结果显示关键技术的排序'''
    word = request.GET.get('word', None)
    queryset = Paper.objects()
    year_count = {}
    if not word:
        return HttpResponse("请输入技术关键词(关键词/标题)进行研究热点展示。")
    result = select_research(queryset=queryset, word=word)
    if result is None or result.count() is 0:
        return HttpResponse('未查询到结果。')
    else:
        for paper in result:
            if paper.year is not None:

                if paper.year in year_count:
                    year_count[paper.year] += 1
                else:
                    year_count[paper.year] = 1
        res = json.dumps(year_count, indent=4, ensure_ascii=False)
        return HttpResponse(res, content_type='application/json', charset='utf-8')

# def research_year(request):
#     '''科研热点库--由搜索结果显示排名前10的关键词按年发文量'''
#     word = request.GET.get('word', None)
#     queryset = Paper.objects()
#     year_count = {}
#     result_rank = {}
#     research_author = {}
#     k = {}
#     if not word:
#         return HttpResponse('请输入技术关键词(关键词/标题)进行研究热点展示。')
#     result = select_research(queryset=queryset, word=word)
#     if result is None or result.count() is 0:
#         return HttpResponse('未查询到结果。')
#     else:
#         for paper in result:
#             if paper.keywords is not None and paper.year is not None:
#                 for j in paper.keywords:
#                     if j in year_count:
#                         year_count[j].append(paper.year)
#                     else:
#                         year_count[j] = [paper.year]
#
#         for key, value in year_count.items():
#             result_rank[key] = len(value)
#         sort_rank = sorted(result_rank.items(), key=lambda x: x[1], reverse=True)[1:11]  # 选取排名前10的关键词,删除查询使用的keywords。
#         for i in sort_rank:  # 将排序前10的关键词写入新的字典中
#             k[i[0]] = year_count[i[0]]
#
#         for key, value in k.items():
#             research_author[key] = {}
#             for i in k[key]:
#                 if i in research_author[key]:
#                     research_author[key][i] += 1
#                 else:
#                     research_author[key][i] = 1
#
#         if len(research_author) is 0:
#             return HttpResponse('该研究方向没有对应关键词数据，请输入其他研究方向关键词进行查询。')
#         else:
#             # return JsonResponse(research_author, json_dumps_params={'ensure_ascii': False})
#             res = json.dumps(research_author, indent=4, ensure_ascii=False)
#             return HttpResponse(res, content_type='application/json', charset='utf-8')

def research_authors(request):
    '''科研热点库--由关键词统计作者发文量情况'''
    word = request.GET.get('word', None)
    r_authors = {}
    k = {}
    r_y_authors = {}
    queryset = Paper.objects()
    if not word:
        return HttpResponse('请输入技术关键词(关键词/标题)进行研究热点展示。')
    result = select_research(queryset=queryset, word=word)
    if result is None or result.count() is 0:
        return HttpResponse('未查询到结果。')
    else:
        for paper in result:
            if paper.authors is not None and len(paper.authors) != 0:
                if paper.year is not None:
                    for j in range(len(paper.authors)):

                        # 英文名称考虑正序和倒序两种情况
                        reverse_name = paper.authors[j]['name'].split(' ')
                        reverse_name_list = list(reverse_name)
                        reverse_name_list.reverse()
                        rev_name = " ".join(i for i in reverse_name_list)

                        if paper.authors[j]['name'] in r_authors:
                            r_authors[paper.authors[j]['name']].append(paper.year)
                        elif rev_name in r_authors:
                            r_authors[rev_name].append(paper.year)
                        else:
                            r_authors[paper.authors[j]['name']] = [paper.year]

        result_rank = {}
        for key, value in r_authors.items():
            result_rank[key] = len(value)
        sort_rank = sorted(result_rank.items(), key=lambda x: x[1], reverse=True)[:10]     # 选取发文量排名前10的研究人员
        for i in sort_rank:                    # 将排序前10的关键词写入新的字典中
            k[i[0]] = r_authors[i[0]]

        for key, value in k.items():
            r_y_authors[key] = {}
            for i in k[key]:
                if i in r_y_authors[key]:
                    r_y_authors[key][i] += 1
                else:
                    r_y_authors[key][i] = 1
        if len(r_y_authors) is 0:
            return HttpResponse('该研究人员没有对应文章数据或关键词数据，请输入其他研究人员进行查询。')
        else:
            # return JsonResponse(r_y_authors, json_dumps_params={'ensure_ascii': False})
            res = json.dumps(r_y_authors, indent=4, ensure_ascii=False)
            return HttpResponse(res, content_type='application/json', charset='utf-8')

def research_orgs(request):
    '''科研热点库--由机构名称统计机构发文量情况.
       观察数据库：使用paper的author.org/year/keywords字段，统计机构关键词按年发文量随时间变化曲线。
       使用author数据库中的pubs字段。
    '''

    org = request.GET.get('org', None)
    info = request.GET.get('info', None)
    queryset = Author.objects()
    a = {}
    b = {}
    k = {}
    papers = {}
    if not (org or info):
        return HttpResponse('请输入机构名称/关键词进行研究热点展示。')
    result = select_research_org(queryset, org=org, info=info)
    if result is None or len(result) is 0:
        return HttpResponse('未查询到结果。')
    else:
        for i in range(len(result)):
            papers[i] = []
            for j in range(len(result[i].pubs)):
                papers[i].append(result[i].pubs[j].i.fetch())
        for key, value in papers.items():
            for i in papers[key]:
                if i.year is None:
                    continue
                else:
                    if i.keywords is None:
                        continue
                    else:
                        for j in i.keywords:
                            if j in a:
                                a[j].append(i.year)
                            else:
                                a[j] = [i.year]

        # 因为对应的关键词较多，选取排名前10的关键词进行展示

        result_rank = {}
        for key, value in a.items():
            result_rank[key] = len(value)
        sort_rank = sorted(result_rank.items(), key=lambda x: x[1], reverse=True)[:10]     # 选取前10的关键词
        for i in sort_rank:                    # 将排序前10的关键词写入新的字典中
            k[i[0]] = a[i[0]]

        for key, value in k.items():
            b[key] = {}
            for i in k[key]:
                if i in b[key]:
                    b[key][i] += 1
                else:
                    b[key][i] = 1
        if len(b) is 0:
            return HttpResponse('该机构没有对应文章数据或关键词数据，请输入其他机构名称进行查询。')
        else:
            # return JsonResponse(b, json_dumps_params={'ensure_ascii': False})
            res = json.dumps(b, indent=4, ensure_ascii=False)
            return HttpResponse(res, content_type='application/json', charset='utf-8')

    # 下述用来统计机构按年发文量变化情况
    # org = request.GET.get('org', None)
    # queryset = Paper.objects()
    # a = {}
    # years = []
    # research_org = {}
    # if not org:
    #     return HttpResponse('请输入机构名称进行研究热点展示。')
    # result = select_research_org(queryset, org=org)
    # if result is None or result.count() is 0:
    #     return HttpResponse('未查询到结果。')
    # else:
    #     for paper in result:
    #         if paper.authors is not None and len(paper.authors) != 0:
    #             for i in range(len(paper.authors)):
    #                 if 'org' not in paper.authors[i]:
    #                     continue
    #                 elif paper.authors[i]['org'] is not None:
    #                     if paper.year is not None:
    #                         if paper.authors[i]['org'] in a:
    #                             a[paper.authors[i]['org']].append(paper.year)
    #                         else:
    #                             a[paper.authors[i]['org']] = [paper.year]
    #
    #     # 机构需正则匹配
    #     re_org = '.*' + org + '.*'
    #     pattern = re.compile(re_org, re.IGNORECASE)
    #
    #     for key, value in a.items():
    #         if pattern.search(key):
    #             for i in a[key]:
    #                 years.append(i)
    #
    #     for i in years:
    #         if i in research_org:
    #             research_org[i] += 1
    #         else:
    #             research_org[i] = 1
    # return JsonResponse(research_org, json_dumps_params={'ensure_ascii': False})


def research_single_author(request):
    '''科研热点库--由作者名称统计按年发文情况.
       可以通过author数据库找paper/可以从paper数据库找作者名称(需要使用正则表达式等).为了简单,使用作者对应的paper寻找关键词按年统计结果.
       与author_tags_year不同,虽然均是针对单一作者关键词按年统计.
       author_tags_year提供作者id字段,research_single_author提供作者姓名.其他同。
    '''
    name = request.GET.get('name', None)
    info = request.GET.get('info', None)
    queryset = Author.objects()
    a = {}
    k = {}
    research_author = {}
    if not (name or info):
        return HttpResponse('请输入作者名称/关键词进行研究热点展示。')
    result = select_research_author(queryset, name=name, info=info)[0]
    if result is None or len(result) is 0:
        return HttpResponse('未查询到结果。')
    else:
        papers = []
        n_pubs_range = range(len(result.pubs))
        for i in n_pubs_range:
            papers.append(result.pubs[i].i.fetch())
        for i in papers:
            if i.year is None:
                continue
            else:
                if i.keywords is None:
                    continue
                else:
                    for j in i.keywords:
                        if j in a:
                            a[j].append(i.year)
                        else:
                            a[j] = [i.year]

        result_rank = {}
        for key, value in a.items():
            result_rank[key] = len(value)
        sort_rank = sorted(result_rank.items(), key=lambda x: x[1], reverse=True)[:10]     # 选取前10的关键词
        for i in sort_rank:                    # 将排序前10的关键词写入新的字典中
            k[i[0]] = a[i[0]]

        for key, value in k.items():
            research_author[key] = {}
            for i in k[key]:
                if i in research_author[key]:
                    research_author[key][i] += 1
                else:
                    research_author[key][i] = 1
        if len(research_author) is 0:
            return HttpResponse('该作者没有对应文章数据或关键词数据，请输入其他作者名称进行查询。')
        else:
            # return JsonResponse(research_author, json_dumps_params={'ensure_ascii': False})
            res = json.dumps(research_author, indent=4, ensure_ascii=False)
            return HttpResponse(res, content_type='application/json', charset='utf-8')
    #     for paper in result:
    #         if paper.authors is not None and len(paper.authors) != 0:
    #             for i in range(len(paper.authors)):
    #                 if 'name' not in paper.authors[i]:
    #                     continue
    #                 elif paper.authors[i]['name'] is not None:
    #                     if paper.year is not None:
    #                         reverse_name = paper.authors[i]['name'].split(' ')
    #                         reverse_name_list = list(reverse_name)
    #                         reverse_name_list.reverse()
    #                         rev_name = " ".join(i for i in reverse_name_list)
    #                         if paper.authors[i]['name'] in a:
    #                             a[paper.authors[i]['name']].append(paper.year)
    #                         elif rev_name in a:
    #                             a[rev_name].append(paper.year)
    #                         else:
    #                             a[paper.authors[i]['name']] = [paper.year]
    #     re_org = '.*' + author + '.*'
    #     pattern = re.compile(re_org, re.IGNORECASE)
    #
    #     k = []
    #     for key, value in a.items():
    #         if pattern.search(key):
    #             for i in a[key]:
    #                 k.append(i)
    #
    #     for i in k:
    #         if i in research_author:
    #             research_author[i] += 1
    #         else:
    #             research_author[i] = 1

def index(request):
    """
    主页
    :param request:
    :return:
    """
    return render(request=request, template_name='expert_info.html')


def icon_upload(request):
    """
    上传 author 图片处理
    :param request: 表单数据需要有用户 id 和文件
    :return:
    """
    if request.POST:
        icon_file: InMemoryUploadedFile = request.FILES['icon']
        # 将 InMemoryUploadedFile 转化为 PIL 类型数据
        # icon = Image.open(icon_file)
        # 处理 PIL 类型数据
        id = str(request.POST['id'])
        # 处理
        update_author_icon(id=id, icon_file=icon_file)
    return HttpResponse('successfuly uploaded')

class VenueViewSet(viewsets.ModelViewSet):
    """
    venue api 页面
    """
    serializer_class = VenueSerializer
    queryset = Venue.objects
    pagination_class = StandardResultSetPagination

class CustomAuthToken(ObtainAuthToken):
    """
    权限控制相关类，自定义 Token
    """
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user_id': user.pk,
            'email': user.email
        })

def author_count(request):
    '''对专家学者、机构和论文数量进行统计'''
    count = {}
    count['专家数量'] = Author.objects.all().count()
    count['学术资源'] = Paper.objects.all().count()
    # django 优化数据查询, orgs排除空值和空字符串
    a = Author.objects.filter(orgs=None).count()
    b = Author.objects.filter(orgs=[""]).count()
    count['优化数量'] = count['专家数量']-a-b
    # return JsonResponse(count, json_dumps_params={'ensure_ascii': False})
    res = json.dumps(count, indent=4, ensure_ascii=False)
    return HttpResponse(res, content_type='application/json', charset='utf-8')

